package cn.iocoder.yudao.module.pay.order.controller.admin;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.module.api.pay.order.eums.UnifiedOrderStatusEnum;
import cn.iocoder.yudao.module.pay.order.convert.PayOrderConvert;
import cn.iocoder.yudao.module.pay.order.dal.dataobject.PayOrderDO;
import cn.iocoder.yudao.module.pay.order.service.PayOrderService;
import cn.iocoder.yudao.module.pay.order.vo.*;
import com.google.common.collect.Maps;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserType;
import static cn.iocoder.yudao.module.api.pay.ErrorCodeConstants.PAY_ORDER_NOT_FOUND;

@Tag(name = "管理后台 - 付款单据")
@RestController
@RequestMapping("/pay/order")
@Validated
public class PayOrderController {

    @Resource
    private PayOrderService payOrderService;

    @GetMapping("/get")
    @Operation(summary = "获得付款单据")
    @Parameters({
            @Parameter(name = "id", description = "支付编号", example = "1863170925660639233"),
            @Parameter(name = "no", description = "支付单号", example = "PAY202412011838591"),
            @Parameter(name = "tradeNo", description = "交易单号", example = "TRD202412011838591"),
            @Parameter(name = "sync", description = "是否同步订单的第三方支付渠道的支付状态", example = "true")
    })
    @PreAuthorize("@ss.hasPermission('pay:order:query')")
    public CommonResult<PayOrderRespVO> getOrder(@RequestParam(value = "id", required = false) Long id,
                                                 @RequestParam(value = "no", required = false) String no,
                                                 @RequestParam(value = "tradeNo", required = false) String tradeNo,
                                                 @RequestParam(value = "sync", required = false) Boolean sync) {
        PayOrderDO order;
        if (id != null && id > 0) {
            order = payOrderService.getOrder(id);
        } else if (StrUtil.isNotBlank(no)) {
            order = payOrderService.getOrderByNo(no);
        } else if (StrUtil.isNotBlank(tradeNo)) {
            order = payOrderService.getOrderByTradeNo(tradeNo);
        } else {
            throw exception(PAY_ORDER_NOT_FOUND);
        }
        if (order == null) {
            return success(null);
        }
        // sync 仅在等待支付
        if (Boolean.TRUE.equals(sync) && UnifiedOrderStatusEnum.isWaiting(order.getStatus())) {
            payOrderService.syncOrder(order);
            // 重新查询，因为同步后，可能会有变化
            order = payOrderService.getOrderByTradeNo(order.getTradeNo());
        }
        return success(BeanUtils.toBean(order, PayOrderRespVO.class));
    }

    @GetMapping("/get-detail")
    @Operation(summary = "获得付款单据详情")
    @Parameter(name = "id", description = "支付编号", example = "1863170925660639233")
    @Parameter(name = "no", description = "支付单号", example = "PAY202412011838591")
    @Parameter(name = "tradeNo", description = "交易单号", example = "TRD202412011838591")
    @PreAuthorize("@ss.hasPermission('pay:order:query')")
    public CommonResult<PayOrderDetailsRespVO> getOrderDetail(@RequestParam(value = "id", required = false) Long id,
                                                              @RequestParam(value = "no", required = false) String no,
                                                              @RequestParam(value = "tradeNo", required = false) String tradeNo) {
        PayOrderDO order;
        if (id != null && id > 0) {
            order = payOrderService.getOrder(id);
        } else if (StrUtil.isNotBlank(no)) {
            order = payOrderService.getOrderByNo(no);
        } else if (StrUtil.isNotBlank(tradeNo)) {
            order = payOrderService.getOrderByTradeNo(tradeNo);
        } else {
            throw exception(PAY_ORDER_NOT_FOUND);
        }
        if (order == null) {
            return success(null);
        }
        // 拼接返回
        return success(PayOrderConvert.INSTANCE.convertDetail(order));
    }

    @PostMapping("/submit")
    @Operation(summary = "提交付款单据")
    public CommonResult<PayOrderSubmitRespVO> submitPayOrder(@Valid @RequestBody PayOrderSubmitReqVO reqVO) {
        if (reqVO.getChannelExtras() == null) {
            reqVO.setChannelExtras(Maps.newHashMapWithExpectedSize(2));
        }
        // 通过钱包余额支付、微信小程序支付时，默认以当前登录用户的信息进行兜底
        reqVO.getChannelExtras().put("user_id", String.valueOf(getLoginUserId()));
        reqVO.getChannelExtras().put("user_type", String.valueOf(getLoginUserType()));
        PayOrderSubmitRespVO respVO = payOrderService.submitOrder(reqVO);
        return success(respVO);
    }

    @GetMapping("/page")
    @Operation(summary = "获得付款单据分页")
    @PreAuthorize("@ss.hasPermission('pay:order:query')")
    public CommonResult<PageResult<PayOrderPageItemRespVO>> getOrderPage(@Valid PayOrderPageReqVO pageVO) {
        PageResult<PayOrderDO> pageResult = payOrderService.getOrderPage(pageVO);
        if (CollectionUtil.isEmpty(pageResult.getList())) {
            return success(new PageResult<>(pageResult.getTotal()));
        }
        // 拼接返回
        return success(PayOrderConvert.INSTANCE.convertPage(pageResult));
    }

    @GetMapping("/export-excel")
    @Operation(summary = "导出付款单据 Excel")
    @PreAuthorize("@ss.hasPermission('pay:order:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportOrderExcel(@Valid PayOrderExportReqVO exportReqVO,
                                 HttpServletResponse response) throws IOException {
        List<PayOrderDO> list = payOrderService.getOrderList(exportReqVO);
        if (CollectionUtil.isEmpty(list)) {
            ExcelUtils.write(response, "付款单据.xls", "数据",
                    PayOrderExcelRespVO.class, new ArrayList<>());
            return;
        }
        // 拼接返回
        List<PayOrderExcelRespVO> excelList = PayOrderConvert.INSTANCE.convertList(list);
        // 导出 Excel
        ExcelUtils.write(response, "付款单据.xls", "数据", PayOrderExcelRespVO.class, excelList);
    }

}
